﻿#include "camera.h"

#include <QDebug>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <sys/mman.h>
#include <sys/time.h>
#include <QPixmap>
#include <QBuffer>
#include <bitset>
#include <iostream>

//#include <QVariant>
#include "savethread.h"
#include "conversion.h"
#include "command_define.h"
#include <QTime>
#include <QThread>
#include <QProcess>
#include <iostream>
#include <QStorageInfo>
using namespace std;

#define USR_CMD_ADDR 0xa0010000
#define SPI_CMD_ADDR 0xa0020000
#define IMG_CMD_ADDR 0xa0030000

#define IMAGE_WIDTCH        8424
#define IMAGE_HEIGHT        6032
#define DMA_BLOCK_SIZE      2*IMAGE_WIDTCH*IMAGE_HEIGHT
#define DMA_BLOCK_NUM       1
#define IMAGE_SIZE          DMA_BLOCK_SIZE*DMA_BLOCK_NUM

#define TEST_MODE           0
unsigned int sensor_exptime[4]={0x00,0x01,0x1,0x00};
unsigned int win1[4]={0x00,0x00,0x90,0x17};

#define user_test;


//
//QString path1 = "/run/media/nvme0n1p1/";
//QString path2 = "/mnt/";
//
int fd_name = 0;

//gpio
axil_cmd_handle axil_cmd_user;
axil_cmd_handle axil_cmd_spi;

bool dma_success_flag = true;

//unsigned char *image_mid0=(unsigned char *)malloc(IMAGE_SIZE);
//unsigned char *image_mid0=(unsigned char *)malloc(1024*1024*2);



void callbackafterrecieve(int channel_id, void *data){
//    qDebug()<<"callback";
    dma_success_flag = false;
//    qDebug() << "callback" << QDateTime::currentDateTime().toString("yyyyy-MM-dd hh:mm:ss.zzz") << dma_success_flag;
}

Camera::Camera(QObject *parent) :
    QObject(parent)
{
    //    pworkThread->start();

    //    qRegisterMetaType<axidma_dev_t>("axidma_dev_t");//信号与槽传递自定义类型需要注册
    dma_success_flag_time_ = new QTimer(this);

    waitSave = new WaitSave;
    QThread* thread = new QThread;
    waitSave->moveToThread(thread);
    thread->start();
    connect(waitSave,&WaitSave::pictureOver,this,&Camera::pictureOverTrans);
    connect(dma_success_flag_time_,&QTimer::timeout,waitSave,&WaitSave::saveAndTrans);

    dma_success_flag_time_->start(dma_success_flag_timeout_);
    //    emit beginSaveAndTrans();
//    qDebug() << QThread::currentThreadId()<<"this";
}

Camera::~Camera()
{
//    qDebug()<< "runing stop!!!!!!!!!!!!!!!!!!";
    axidma_stop_transfer(axidma_dev,rx_chans->data[0]);
    //    pworkThread->stop();
    //    pworkThread->quit();
    //    pworkThread->wait(1000);
    //    pworkThread->deleteLater();
}

bool Camera::CameraInit()
{
    bool res;
    image_mid0=(unsigned char *)malloc(IMAGE_SIZE);
    if(image_mid0 == nullptr){
        qDebug() << "image_mid0 error!!!";
        return false;
    }
//    qDebug() << "image_mid0:" << image_mid0;
    res = cameraRestart();
    return res;
}

int Camera::CameraExternTrigger()
{
    return Command::CsCommandOk;
}

int Camera::GetCameraInfo(CameraSpace::CameraInfo &info)
{
    getStorageSize();
    getTemperature();
    info = cameraInfo;
    return Command::CsCommandOk;
}

int Camera::SetCameraMode(unsigned char mode, unsigned char &current_mode)
{
    cameraInfo.exposureMode = mode;
    current_mode = cameraInfo.exposureMode;
    waitSave->updataData(cameraInfo.picStartX,cameraInfo.picStartY,cameraInfo.picWidth,cameraInfo.picHeight,cameraInfo.exposureMode,cameraInfo.saveLocation);
    return Command::CsCommandOk;
}

int Camera::SetTriggerSource(unsigned char source, unsigned char &current_source)
{
    sensor_success_access_num_ = axil_cmd_get(&axil_cmd_user,USER_REVEIVE_SUCCESS_CNT);
    axil_cmd_set(&axil_cmd_user,USER_STOP_EXP,0);
    axil_cmd_set(&axil_cmd_user,USER_CAMERA_MODE,0);
    if(1 == source){
        source = 0;
    }
    unsigned int temp;
    axil_cmd_set(&axil_cmd_user,USER_PHOTO_MODE,source);
    axil_cmd_set(&axil_cmd_user,USER_CAMERA_MODE,0x2);
    temp = axil_cmd_get(&axil_cmd_user,USER_PHOTO_MODE);
    current_source = temp&0xf;
    cameraInfo.triggerSource = current_source;
    if(0 == (temp&0xf)){
        current_source = CameraSpace::Internal;
        cameraInfo.triggerSource = CameraSpace::Internal;
    }

    if(firstFlag){
        firstFlag = false;
        axidma_oneway_transfer(axidma_dev,rx_chans->data[0],rx_buf,DMA_BLOCK_SIZE,false);
        axil_cmd_set(&axil_cmd_user,USER_DMA_RDY,0x1);
    }

    //        axil_cmd_set(&axil_cmd_user,USER_TRIGGER,0x1);
    //        axil_cmd_set(&axil_cmd_user,USER_STOP_EXP,0);

    return Command::CsCommandOk;
}

int Camera::TriggerOne(QList<QByteArray> &list)
{
    // Begin timing
    for(int i =0;i < DMA_BLOCK_NUM;i++){
        if(firstFlag){
            firstFlag = false;
            axidma_oneway_transfer(axidma_dev,rx_chans->data[0],rx_buf,DMA_BLOCK_SIZE,false);
            axil_cmd_set(&axil_cmd_user,USER_DMA_RDY,0x1);
        }
#ifdef user_test
//        qDebug() << "trigger" << QDateTime::currentDateTime().toString("yyyyy-MM-dd hh:mm:ss.zzz");
        axil_cmd_set(&axil_cmd_user,USER_TRIGGER,0x1);
#else
        sensor_user_trigger_once();
        qDebug()<<"12";
#endif

    }
    //    dma_success_flag = false;//测试图像传输使用
    //    qDebug() << "axidma_dev"<<axidma_dev<<"rx_chans"<<rx_chans<<"rx_buf"<<rx_buf;
    //    listTrans = &list;
    //    waitSave->setData(&dma_success_flag,axidma_dev, rx_chans, rx_buf,&axil_cmd_user,image_mid0,&fd_name,
    //                      &cameraIndex,cameraInfo,listTrans);
    //    qDebug() << QThread::currentThreadId();
    //    qDebug() << &list;
    //    QtConcurrent::run(this,&Camera::WaitSave,&list);
    return Command::CsCommandOk;
}

int Camera::TriggerMore(QList<QByteArray> &list)
{
    listTrans = &list;
    triggerTime = new QTimer(this);
    connect(triggerTime,&QTimer::timeout,this,&Camera::TimeOutTrigger);
    triggerTime->start(timeOut);
    return Command::CsCommandOk;
}

int Camera::TriggerStop()
{
    if(triggerTime->isActive()){
        triggerTime->stop();
    }
    return Command::CsCommandOk;
}





//int Camera::WaitSave(QList<QByteArray>* list)
//{
//    qDebug() << list;
//    qDebug() << QThread::currentThreadId();
//    qDebug() << "dma_success_flag start";
//    while(dma_success_flag){
//        QThread::msleep(1);
//        qDebug() << "in while";
//    }
//    dma_success_flag = true;
//    qDebug() << "dma_success_flag pass";
//    axidma_oneway_transfer(axidma_dev,rx_chans->data[0],rx_buf,DMA_BLOCK_SIZE,false);
//    axil_cmd_set(&axil_cmd_user,USER_DMA_RDY,0x1);
////    memcpy(&image_mid0[DMA_BLOCK_SIZE],(unsigned char *)rx_buf,DMA_BLOCK_SIZE);
//    memcpy(image_mid0,(unsigned char *)rx_buf,DMA_BLOCK_SIZE);
////        axidma_stop_transfer(axidma_dev,rx_chans->data[0]);
//fd_name++;
//// End timing
//// Compute the throughput of each channel

//image = QImage(image_mid0,IMAGE_WIDTCH,IMAGE_HEIGHT,QImage::Format_Grayscale16);
////    qDebug() << "getImage" << QDateTime::currentDateTime().toString("yyyyy-MM-dd hh:mm:ss.zzz");
////    image = image.mirrored(true, false);
//QString load1 = path1 + QString("%1%2%3").arg("gtest",QString::number(cameraIndex),".tiff");
//QString load2 = path2 + QString("%1%2%3").arg("gtest",QString::number(cameraIndex),".tiff");
//if(cameraInfo.exposureMode != CameraSpace::OnlyShow){
//    if(IMAGE_WIDTCH != cameraInfo.picWidth || IMAGE_HEIGHT != cameraInfo.picHeight){
//        QRect temp_rect = QRect(cameraInfo.picStartX, cameraInfo.picStartY, cameraInfo.picWidth, cameraInfo.picHeight);
//        QImage temp_img = image.copy(temp_rect);
//        if(cameraInfo.saveLocation == CameraSpace::All){
//            pworkThread->addTask(new SaveTask(temp_img,load1));
//            pworkThread->addTask(new SaveTask(temp_img,load2));
//        }else if(cameraInfo.saveLocation == CameraSpace::In){
//            pworkThread->addTask(new SaveTask(temp_img,load1));
//        }else if(cameraInfo.saveLocation == CameraSpace::Out){
//            pworkThread->addTask(new SaveTask(temp_img,load2));
//        }

//    }else{
//        if(cameraInfo.saveLocation == CameraSpace::All){
//            pworkThread->addTask(new SaveTask(image,load1));
//            pworkThread->addTask(new SaveTask(image,load2));
//        }else if(cameraInfo.saveLocation == CameraSpace::In){
//            pworkThread->addTask(new SaveTask(image,load1));
//        }else if(cameraInfo.saveLocation == CameraSpace::Out){
//            pworkThread->addTask(new SaveTask(image,load2));
//        }
//    }
//    qDebug() << "end.........";
//}

//if(cameraInfo.exposureMode != CameraSpace::OnlySave){
//    QImage send_image;
//    if(IMAGE_WIDTCH != cameraInfo.picWidth || IMAGE_HEIGHT != cameraInfo.picHeight){
//        QRect temp_rect = QRect(cameraInfo.picStartX, cameraInfo.picStartY, cameraInfo.picWidth, cameraInfo.picHeight);
//        send_image = image.copy(temp_rect);
//        send_image = send_image.scaled(800, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation);
//    }else{
//        send_image = image.scaled(800, 600, Qt::KeepAspectRatio, Qt::SmoothTransformation);
//    }

//    send_image = send_image.convertToFormat(QImage::Format_Grayscale16);
//    for(int i = 0 ; i < 60; i++)
//    {
//        QImage img1 = send_image.copy(0, i*10, 800, 10);
//        QByteArray byteArray;
//        byteArray.resize(img1.byteCount());
//        QDataStream data(&byteArray, QIODevice::ReadWrite);
//        data<< img1;
//        QByteArray a;
//        a.append(IntToArray(1));
//        a.append(ShortToArray(600));
//        a.append(ShortToArray(static_cast<unsigned short>(i)*10));
//        a.append(ShortToArray((1 + static_cast<unsigned short>(i))*10));
//        a.append(ShortToArray(800));
//        a.append(byteArray);
//        list->append(a);
//    }
//}
//emit pictureOver();
//cameraIndex++;
//}


int Camera::SetExposureTime(quint16 time, quint16 &current_time)
{
    if(exposureing_state_ != ((axil_cmd_get(&axil_cmd_user,USER_TRIGGER_STATUS)&0x80000000)>>31)){
//        qDebug() << "SetExposureTime2222222222222222";
        QThread::usleep(300000);
        //        QTimer::singleShot(300, this, [=](){
        quint32 inputTime = time*1000/50-1140;
        //    cameraInfo.exposureTime = (inputTime+1140)*16.666666/1000;

        axil_cmd_set(&axil_cmd_user,USER_TEXP0_EXP_LOW,inputTime);
        axil_cmd_set(&axil_cmd_user,USER_TEXP0_EXP_HIGH,0x00);
        if(inputTime == axil_cmd_get(&axil_cmd_user,USER_TEXP0_EXP_LOW)){
            cameraInfo.exposureTime = time;
        }
        //        });


    }
    current_time = cameraInfo.exposureTime;
    return Command::CsCommandOk;
}

int Camera::SetFrame(quint16 frame, quint16 &current_frame)
{
    cameraInfo.frameTime = frame;
    current_frame = cameraInfo.frameTime;
    return Command::CsCommandOk;
}

int Camera::SetAnologGain(unsigned char gain, unsigned char &current_gain)
{
    cameraInfo.analogGain = gain;
    unsigned int real_gain = (gain) & 0x3F;
    unsigned int status;
    status=sensor_spi_read(103);//103为sensor芯片手册中的103号寄存器
    sensor_spi_write(103,((status&0xc0)|real_gain));
    unsigned int c = sensor_spi_read(103);
    current_gain = c& 0x3F;
    cameraInfo.analogGain = current_gain;
    return Command::CsCommandOk;
}

//int Camera::SetDigiGain(unsigned char gain, unsigned char &current_gain)
//{
//    cameraInfo.digitalGain = gain;
//    current_gain = cameraInfo.digitalGain;
//    return Command::CsCommandOk;
//}

int Camera::SetWindow(CameraSpace::CameraWindow window, CameraSpace::CameraWindow &current_window)
{
    cameraInfo.picStartX = window.picStartX;
    cameraInfo.picWidth = window.picWidth;
    cameraInfo.picStartY = window.picStartY;
    cameraInfo.picHeight = window.picHeight;
    current_window = window;
    if(window.picWidth != IMAGE_WIDTCH || window.picHeight != IMAGE_HEIGHT){
        cameraInfo.picWidth = 800;
        cameraInfo.picHeight = 600;
    }
    waitSave->updataData(cameraInfo.picStartX,cameraInfo.picStartY,cameraInfo.picWidth,cameraInfo.picHeight,cameraInfo.exposureMode,cameraInfo.saveLocation);
    return Command::CsCommandOk;
}

int Camera::GetTemp(quint16 &temp)
{
    unsigned int temperature;
    temperature = axil_cmd_get(&axil_cmd_user,USER_SENSOR_TEMP);
    temp = (temperature&0xffff);
    cameraInfo.tempx10 = (temperature&0xffff)*10;
//    qDebug() << temperature << (temperature&0xffff);
    return Command::CsCommandOk;
}

int Camera::getStorageSize()
{
    //    QString dir0 = "/run/media/nvme0n1";
    //    QString dir = "/mnt";
    QString dir0 = "/mnt/mnt1";
    QString dir = "/mnt/mnt2";
    QList<QStorageInfo> storageInfoList = QStorageInfo::mountedVolumes();
    //    qDebug() << storageInfoList;
    foreach (QStorageInfo storage, storageInfoList) {
//        qDebug() << storage;
        if(storage.rootPath().contains(dir0)){
            cameraInfo.intStorageSize = storage.bytesAvailable()/1048576;
        }
        if(storage.rootPath().contains(dir)){
            cameraInfo.outStorageSize = storage.bytesAvailable()/1048576;
        }
    }
    return Command::CsCommandOk;
}

int Camera::getTemperature()
{
    unsigned int temperature;
    temperature = axil_cmd_get(&axil_cmd_user,USER_SENSOR_TEMP);
//    qDebug() << temperature;
    cameraInfo.tempx10 = (temperature&0xffff)*10;
    return Command::CsCommandOk;
}

int Camera::SetpicTMode(unsigned char mode, unsigned char &current_mode)
{
    cameraInfo.pictureType = mode;
    //    current_mode = cameraInfo.pictureType;
    unsigned int status;
    status=sensor_spi_read(1);
    if(mode == CameraSpace::Actual){
        sensor_spi_write(1,status&0xfe);
    }else if(mode == CameraSpace::Test){
        sensor_spi_write(1,status|0x01);
    }else{
        return Command::CsCommandOk;
    }
    status=sensor_spi_read(1);
    if((status&0x1) == 1){
        current_mode = CameraSpace::Test;
    }else if((status&0x1) == 0){
        current_mode = CameraSpace::Actual;
    }
    //    qDebug() << current_mode;
    return Command::CsCommandOk;
}

int Camera::RecoverCamera(unsigned char &res)
{
    bool value = cameraRestart();
    if(value){
        res = Command::CsCommandOk;
    }else{
        res = Command::CsError;
    }

    return res;
}

int Camera::SetSaveLocation(unsigned char mode, unsigned char &current_mode)
{
    cameraInfo.saveLocation = mode;
    //    if(cameraInfo.saveLocation)
    current_mode = cameraInfo.saveLocation;
    waitSave->updataData(cameraInfo.picStartX,cameraInfo.picStartY,cameraInfo.picWidth,cameraInfo.picHeight,cameraInfo.exposureMode,cameraInfo.saveLocation);
    return Command::CsCommandOk;
}

int Camera::SetPhotoMessage(QByteArray photo_message, QByteArray &current_photo_message)
{
    photo_file_message_ = photo_message;
    waitSave->SendPhotoMessage(photo_message);
    current_photo_message = photo_file_message_;
    return Command::CsCommandOk;
}

void Camera::releaseMemory()
{
    axil_cmd_set(&axil_cmd_user,USER_RESET_SENSOR,0x0);
    axidma_stop_transfer(axidma_dev,rx_chans->data[0]);
    //    free(rx_buf);
    //    rx_buf = nullptr;
    free(image_mid0);
    image_mid0 = nullptr;
}

void Camera::getListAdd(QList<QByteArray> *list)
{
    listTrans = list;
    waitSave->setPoint(list);
}

void Camera::TimeOutTrigger()
{
    // Begin timing
    for(int i =0;i < DMA_BLOCK_NUM;i++){
        if(firstFlag){
            firstFlag = false;
            axidma_oneway_transfer(axidma_dev,rx_chans->data[0],rx_buf,DMA_BLOCK_SIZE,false);
            axil_cmd_set(&axil_cmd_user,USER_DMA_RDY,0x1);
        }
    }
//    qDebug() << "trigger" << QDateTime::currentDateTime().toString("yyyyy-MM-dd hh:mm:ss.zzz");
    axil_cmd_set(&axil_cmd_user,USER_TRIGGER,0x1);
    //    qDebug() << "axidma_dev"<<axidma_dev<<"rx_chans"<<rx_chans<<"rx_buf"<<rx_buf;

}

bool Camera::DetectionExternalTrigger()
{
    if(sensor_success_access_num_ < axil_cmd_get(&axil_cmd_user,USER_REVEIVE_SUCCESS_CNT)){

        sensor_success_access_num_ = axil_cmd_get(&axil_cmd_user,USER_REVEIVE_SUCCESS_CNT);
        return true;
    }
    return false;
}

void Camera::SetDeviceNum(const unsigned char k_device_num)
{
    waitSave->SetDeviceNum(k_device_num);
}


QByteArray Camera::IntToArray(int v)
{
    int size = sizeof (int);

    QByteArray a;
    a.resize(size);

    for(int i = 0; i < size; i++){
        a[i] = static_cast<char>( (v >> ( (size - i -1) * 8) ) & 0xff );
    }

    return a;
}

QByteArray Camera::ShortToArray(unsigned short v)
{
    int size = sizeof (unsigned short);

    QByteArray a;
    a.resize(size);

    for(int i = 0; i < size; i++){
        a[i] = static_cast<char>( (v >> ( (size - i -1) * 8) ) & 0xff );
    }

    return a;
}

bool Camera::cameraRestart()
{
    int rc;
    int rx_channel;
    int cnt = 0;

    printf("\timage Size: %0.2f MiB\n", BYTE_TO_MIB(IMAGE_SIZE));

    // ///////////////////
    //initial axil
    axil_cmd_setup(&axil_cmd_user, USR_CMD_ADDR);
    axil_cmd_setup(&axil_cmd_spi, SPI_CMD_ADDR);
    // init start
    //   init the sensor rstn
    axil_cmd_set(&axil_cmd_user,USER_RESET_SENSOR,0x1);
    usleep(10000);
    //  init the sensor register
    axil_cmd_set(&axil_cmd_spi,SPI_RESET_OFFSET,0x1);

    for(uint i=0;i<370;i++){
        axil_cmd_set(&axil_cmd_spi,SPI_TX_OFFSET,(((0x1<<17) | ((i&0x1FF) << 8)) | (sensor_config[i]&0xFF)));
    }
    usleep(10000);
    //set sensor output training word
    axil_cmd_set(&axil_cmd_spi,SPI_TX_OFFSET,((0x1<<17) | 0x57));
    usleep(5);
    usleep(500000);
    for(int i = 0; i <= 10; i++){
        //reset the fpga rtl
        axil_cmd_set(&axil_cmd_user,USER_RESET_RTL,0x1);
        usleep(10);
        axil_cmd_set(&axil_cmd_user,USER_RESET_RTL,0x0);
        usleep(1000);

        axil_cmd_set(&axil_cmd_user,USER_START_TRAINING,0x3);
        usleep(10000);

        while((axil_cmd_get(&axil_cmd_user,USER_TRAINING_STATUS)&0x3)!=0x3);

        if ((axil_cmd_get(&axil_cmd_user,USER_TRAINING_STATUS)&0x3fff0000)==0x0)
            break;
        if(i == 10)
        {
            printf("interface word align error \n");
            break;
        }
    }
    //    //reset the fpga rtl
    //    axil_cmd_set(&axil_cmd_user,USER_RESET_RTL,0x1);
    //    usleep(10);
    //    axil_cmd_set(&axil_cmd_user,USER_RESET_RTL,0x0);
    //    usleep(10);
    //clear all count
    axil_cmd_set(&axil_cmd_user,USER_CLR_TRIGGER,0x1);

    //traing ok set this bit to 1 then fpga can trigger
    axil_cmd_set(&axil_cmd_user,USER_INIT_OK,0x1);
    //set exp
    axil_cmd_set(&axil_cmd_user,USER_TEXP0_EXP_LOW,0x1822C - 1140);// 5ms unit unit 50ns min 1145 1145*16.666666=19.083us
    axil_cmd_set(&axil_cmd_user,USER_TEXP0_EXP_HIGH,0x00);
    //set gap
    axil_cmd_set(&axil_cmd_user,USER_TEXP0_GAP_LOW,0x1822C-1140+0x5B8D80);//+300ms  unit 50ns
    axil_cmd_set(&axil_cmd_user,USER_TEXP0_GAP_HIGH,0x0);
    //once dma bytes
    axil_cmd_set(&axil_cmd_user,USER_DMA_CNT,IMAGE_SIZE); //set once dma bytes 8424*6032*2 Bytes
    //set work mode
    axil_cmd_set(&axil_cmd_user,USER_CAMERA_MODE,0x1);
    axil_cmd_set(&axil_cmd_user,USER_PHOTO_MODE,0x0);
    axidma_dev = axidma_init();
    if (axidma_dev == nullptr) {
        fprintf(stderr, "Failed to initialize the AXI DMA device.\n");
        rc = 1;
    }
    rx_buf = (char *)axidma_malloc(axidma_dev, DMA_BLOCK_SIZE);
    if (rx_buf == nullptr) {
        perror("Unable to allocate receive buffer from the AXI DMA device");
        rc = -1;
        axidma_free(axidma_dev, rx_buf, DMA_BLOCK_SIZE);
        axidma_destroy(axidma_dev);
    }
    usleep(10000);
    rx_chans = axidma_get_dma_rx(axidma_dev);
    if (rx_chans->len < 1) {
        fprintf(stderr, "Error: No receive channels were found.\n");
        rc = -ENODEV;
        axidma_free(axidma_dev, rx_buf, DMA_BLOCK_SIZE);
        axidma_destroy(axidma_dev);
    }
    if (rx_channel == -1) {
        rx_channel = rx_chans->data[0];
    }
    printf("Using receive channel %d.\n", rx_chans->data[0]);
    axidma_set_callback(axidma_dev,rx_chans->data[0],callbackafterrecieve,nullptr);
    //init end
#if TEST_MODE
    unsigned char cur_mode;
    SetpicTMode(CameraSpace::Test, cur_mode);
    QList<QByteArray> list;
    TriggerOne(list);
#endif
    waitSave->setData(&dma_success_flag,axidma_dev, rx_chans, rx_buf,&axil_cmd_user,image_mid0,&fd_name,
                      &cameraIndex,cameraInfo);
    return true;
}

void Camera::sensor_spi_write(unsigned int TX_ADDR, unsigned int TX_DATA)
{
    axil_cmd_set(&axil_cmd_spi,SPI_TX_OFFSET,(((0x1<<17) | ((TX_ADDR&0x1FF) << 8)) | (TX_DATA&0xFF)));
}

unsigned int Camera::sensor_spi_read(unsigned int RX_ADDR)
{
    axil_cmd_set(&axil_cmd_spi,SPI_TX_OFFSET,((RX_ADDR&0x1FF) << 8));
    return axil_cmd_get(&axil_cmd_spi,SPI_RX_OFFSET);
}

